from OthersMethod import OthersMethod
from loguru import logger
import pytest

others_method = OthersMethod()


class Common:
    def __init__(self):
        """
        多个接口通用的校验写在这里
        """
        pass

    def calc_result_check_proinfo_list(self, res_separate, exps=[]):
        """
        校验单个促销相关的各个字段值，包括促销语和享受次数等，入参为list，可以一次性校验多个促销

        线上线下算价通用

        :param res_separate:分解后的算价结果。格式：{'pros': pros_sort, 'shares': skus_share_info}
        :param exps:期望命中的促销列表，格式：exp = [{'proId_exp': 2021030500000881, 'proSlogan': 'XX', 'showSlogan': 'XX'}]
        """
        verification_res_all = {}
        log_all = [{'info': '\n'}, {'info': '================开始校验返回的单个促销相关的各个字段值================'}]
        proIds = []
        proIds_exp = []
        pros = res_separate['pros']
        for pro in pros:
            proIds.append(pro['proId'])  # 单品促销和bestoffer叠加的时候，如果命中单品促销的商品，在不同的bestoffer促销中做赠品/换购品。且没有剩余主品的情况下，会返回多个单品促销结构
        for exp in exps:
            verification_res = {}
            proId_exp = exp['proId_exp']
            proIds_exp.append(proId_exp)
            for pro in pros:
                if proId_exp == pro['proId']:
                    displayInfo = pro['displayInfo']
                    for key, value in exp.items():
                        if key[-3:] == 'exp':
                            continue
                        if pro.get(key) is not None:
                            if value == pro.get(key):
                                verification_res[key] = [True]
                            else:
                                exc_value = "促销：{}({})，字段{}校验失败，期望返回：{}，实际返回：{}".\
                                    format(proId_exp, pro['proName'], key, value, pro.get(key))
                                verification_res[key] = [False, exc_value]
                        elif displayInfo.get(key) is not None:
                            if value == displayInfo.get(key):
                                verification_res[key] = [True]
                            else:
                                exc_value = "促销：{}({})，字段{}校验失败，期望返回：{}，实际返回：{}".\
                                    format(proId_exp, pro['proName'], key, value, displayInfo.get(key))
                                verification_res[key] = [False, exc_value]
            verification_res_values = []
            for value in verification_res.values():
                verification_res_values.append(value[0])
            if False in verification_res_values:
                err = []
                for key, value in verification_res.items():
                    if False in value:
                        err.append(key)
                log_all.append({'error': '失败！！！促销：{}，存在校验失败字段，具体字段列表：{}'.format(proId_exp, err)})
            else:
                log_all.append({'info': '成功！促销：{}，所有字段值校验均正确：{}'.format(proId_exp, list(verification_res.keys()))})
            verification_res_all[proId_exp] = verification_res

        verification_res = {}
        if sorted(proIds_exp) == sorted(proIds):
            verification_res['促销列表校验结果'] = [True]
            log_all.append({'info': '正确命中所有期望命中的促销：{}'.format(proIds)})
        else:
            exc_value = '期望命中促销列表与实际命中促销列表不一致，期望命中促销：{},实际命中促销：{}'.format(sorted(proIds_exp), sorted(proIds))
            verification_res['促销列表校验结果'] = [False, exc_value]
        verification_res_all['促销列表校验结果'] = verification_res
        return verification_res_all, log_all

    def calc_result_check_price(self, result, res_exp={}):
        """
        只校验返回结果中的最终优惠金额以及应付金额
        线上线下算价通用
        orderTotalSettlePrice:订单的应付金额 即过了所有促销后的金额；
        totalOrigPrice:购物车/订单原始电商总价(以sku的单品促销价计算)；
        totalOrigPrice2:购物车/订单原始电商总价(以sku的单品原始计算)；
        otherCondProDiscountAmount:分类/品牌促销优惠金额；
        totalDiscountAmount:购物车/订单总优惠金额（条件+整单两个维度上的优惠金额）；
        totalDiscountAmount2:总优惠金额二(单品+条件+整单三个维度促销的优惠金额)；
        :param result:算价接口返回的原始算价结果
        :param res_exp:期望校验的字段以及对应值。格式：res_exp = {'orderTotalSettlePrice': 3100}
        """
        logger.info('\n')
        logger.info('================开始校验返回的实际应支付金额是否正确================')
        # 校验返回结果
        verification_res = {}
        for key in res_exp:
            if key in result:
                if res_exp[key] is not None:
                    verification_res[key] = (result[key] == res_exp[key], '促销最终计算结果，字段{}校验失败，期望返回：{}，实际返回：{}'.format(key, res_exp[key], result[key]))
                else:
                    pass
            # elif result['matchedStaffPros'] and result['matchedStaffPros'].get(key, None):     # 员工优惠金额在matchedStaffPro 节点下
            #     verification_res[key] = pytest.assume(result['matchedStaffPro'][key] == res_exp[key], '促销最终计算结果，字段{}校验失败，期望返回：{}，实际返回：{}'.format(key, res_exp[key], result['matchedStaffPro'][key]))
            else:
                verification_res[key] = (str(result.get('key')) == str(res_exp[key]), '促销最终计算结果，字段{}校验失败，期望返回：{}，实际未返回该字段'.format(key, res_exp[key]))

        if False in verification_res.values():
            err = []
            for key, value in verification_res.items():
                if value is False:
                    err.append(key)
            logger.error('失败！！！促销最终计算结果，存在校验失败字段，具体字段列表：{}'.format(err))
        else:
            logger.info('成功！促销最终计算结果，所有字段值校验均正确：{}'.format(verification_res.keys()))

